/*
 * Created on Mar 19, 2005
 * Created by dfhuynh
 */
package edu.mit.simile.longwell.query.bucket;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.apache.log4j.Logger;

import edu.mit.simile.longwell.Cache;
import edu.mit.simile.longwell.Profile;
import edu.mit.simile.longwell.query.IQueryModel;
import edu.mit.simile.longwell.query.Query;
import edu.mit.simile.longwell.query.QueryException;
import edu.mit.simile.longwell.query.Restriction;
import edu.mit.simile.longwell.query.engine.QueryEngine;
import edu.mit.simile.longwell.query.project.IProjection;
import edu.mit.simile.longwell.query.project.IProjector;
import edu.mit.simile.longwell.query.project.ProjectorManager;

/**
 * @author dfhuynh
 */
public class NestedQueryBucketer extends BucketerBase {
	final static private Logger s_logger = Logger.getLogger(NestedQueryBucketer.class);
	
	/**
	 * @param profile
	 */
	public NestedQueryBucketer(Profile profile) {
		super(profile);
	}
	
	/* (non-Javadoc)
	 * @see edu.mit.simile.longwell.query.bucket.IBucketer#getBucket(edu.mit.simile.longwell.query.project.IProjection, java.lang.String)
	 */
	public Set getBucket(IProjection projection, String parameter) throws QueryException{
		Cache resultsToBucket = (Cache) 
			m_projectionToParameterToBucket.get(projection, parameter);
		
		if (resultsToBucket == null) {
			resultsToBucket = new Cache(10, NestedQueryBucketer.class, "results-to-bucket");
			m_projectionToParameterToBucket.put(projection, parameter, resultsToBucket);
		}
		
		Query query = new Query(parameter);
		IQueryModel queryModel = (IQueryModel)
			m_profile.getStructuredModel(IQueryModel.class);
		
		Set results = queryModel.queryObjects(query, false);
		
		Set bucket = (Set) resultsToBucket.get(results);
		if (bucket == null) {
			bucket = projection.getObjectsWithValues(results);
			resultsToBucket.put(results, bucket);
		}
		return bucket;
	}
	
	/* (non-Javadoc)
	 * @see edu.mit.simile.longwell.query.bucket.BucketerBase#internalGetBucket(edu.mit.simile.longwell.query.project.IProjection, java.lang.String)
	 */
	protected Set internalGetBucket(IProjection projection, String parameter) {
		throw new InternalError("We don't use this method.");
	}

	/* (non-Javadoc)
	 * @see edu.mit.simile.longwell.query.bucket.BucketerBase#internalSuggestNarrowingBuckets(edu.mit.simile.longwell.query.project.IProjection, float)
	 */
	protected List internalSuggestNarrowingBuckets(IProjection projection,
			float desirable) {
		return new ArrayList();
	}

	/* (non-Javadoc)
	 * @see edu.mit.simile.longwell.query.bucket.BucketerBase#internalSuggestBroadeningBuckets(edu.mit.simile.longwell.query.project.IProjection, java.lang.String)
	 */
	protected BroadeningResult internalSuggestBroadeningBuckets(
			IProjection projection, String parameter) {
		
		List existingBuckets = new ArrayList();
		
		existingBuckets.add(new Bucket(
			this.getClass().getName(), 
			parameter,
			parameterToDescription(parameter, projection.getLocale()),
			0));

		return new BroadeningResult(existingBuckets, new ArrayList());
	}

	/* (non-Javadoc)
	 * @see edu.mit.simile.longwell.query.bucket.BucketerBase#individualParameterToDescription(java.lang.String, java.lang.String)
	 */
	protected String individualParameterToDescription(
			String parameter,
			String locale) {

		Query 		query = new Query(parameter);
		List 		restrictions = query.getRestrictions();
		String[] 	restrictionDescriptions = new String[restrictions.size()];
		int			i = 0;
		
		QueryEngine queryEngine = (QueryEngine) 
			m_profile.getStructuredModel(IQueryModel.class);
		
		BucketerManager bucketerManager = queryEngine.getBucketerManager();
		ProjectorManager projectorManager = queryEngine.getProjectorManager();
		
		Iterator j = restrictions.iterator();
		while (j.hasNext()) {
			Restriction restriction = (Restriction) j.next();
			
			try {
				IProjector projector = projectorManager.getProjector(
					restriction.m_projectorName, 
					restriction.m_projectorParameter, 
					locale);

				IBucketer bucketer = bucketerManager.getBucketer(
					restriction.m_bucketerName);
				
				restrictionDescriptions[i++] =
					projector.getLabel(locale) + ": " +
					bucketer.parameterToDescription(
							restriction.m_bucketerParameter, locale);
			} catch (QueryException e) {
				s_logger.error(e);
			}
		}

		return concatenateListItems(restrictionDescriptions);
	}
}
